/*
 TRABALHO FINAL DE PROGRAMACAO CONCORRENTE 2013
 FEITO POR:
 Danilo Augusto Silva, 6418678
 Felipe Fukakusa, 6426976
 Jader Bruno Pereira Lima, 6792346
 */

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include <sys/time.h>

//MATRIZ A
float MA[4001][4002];

//MAIN
int main(int argc, char *argv[])
{
    //VARIAVEIS
    int J_ORDER;
    int J_ROW_TEST;
    float J_ERROR;
    int J_ITE_MAX;
    
    int i,j,n,it = 0;
    
    struct timeval startTime;
	struct timeval endTime;
    struct timeval startCPU;
    struct timeval endCPU;
    
    float sum,temp,error,big;
    FILE *file;
    
    //INICIA CONTAGEM DO TEMPO
    gettimeofday( &startTime, NULL );
    double start = startTime.tv_sec + ( startTime.tv_usec / 1000000.0 );
    
    if(file = fopen(argv[1], "r")){
        fscanf(file, "%d\n", &J_ORDER);
        fscanf(file, "%d\n", &J_ROW_TEST);
        fscanf(file, "%f\n", &J_ERROR);
        fscanf(file, "%d\n", &J_ITE_MAX);
        
        printf("J_ORDER = %d\n", J_ORDER);
        printf("J_ROW_TEST = %d\n", J_ROW_TEST);
        printf("J_ERROR = %f\n", J_ERROR);
        printf("J_ITE_MAX = %d\n", J_ITE_MAX);
        
        printf("\nEXECUTANDO PROGRAMA GAUSS_SEIDEL SEQUENCIAL\n");
        
        float X[J_ORDER+1];
        
        for(i = 1; i <= J_ORDER; i++){
            for(j = 1; j <= J_ORDER; j++){
                fscanf(file, "%f ", &MA[i][j]);
            }
            fscanf(file, "\n", &n);
        }
        
        /* PRINT MA
        for(i = 1; i <= J_ORDER; i++){
            for(j = 1; j <= J_ORDER; j++){
                printf("%f ", MA[i][j]);
            }
            printf("\n");
        }
        */
        
        for(i = 1; i <= J_ORDER; i++){
            fscanf(file, "%f\n", &MA[i][J_ORDER+1]);
        }
        
        /* PRINT MB
        for(i = 0; i < J_ORDER; i++){
            printf("%f\n", MA[i][J_ORDER+1]);
        }
        */
        
        for(i=1;i<=J_ORDER+1;i++)
        {
            X[i]=0.0;
        }
        
        
        //INICIA CONTAGEM DO TEMPO DE PROCESSAMENTO
        gettimeofday( &startCPU, NULL );
        double startProc = startCPU.tv_sec + ( startCPU.tv_usec / 1000000.0 );
        //LACO PRINICIPAL DO METODO
        do
        {
            big=0;
            for(i=1;i<=J_ORDER;i++)
            {
                sum=0;
                for(j=1;j<=J_ORDER;j++)
                {
                    if(j!=i)
                    {
                        sum=sum+MA[i][j]*X[j];
                    }
                }
                temp=(MA[i][J_ORDER+1]-sum)/MA[i][i];
                error=fabs(X[i]-temp);
                if(error>big)
                {
                    big=error;
                }
                X[i]=temp;
                //printf("\nx[%d] =%f",i,X[i]);
            }//printf("\n");
        }
        while(big>=J_ERROR && it < J_ITE_MAX);
        //EXECUTA ENQUANTO FOR MAIOR QUE OERRO
        
        //FINALIZA A CONTAGEM DE TEMPO DE PROCESSAMENTO
        gettimeofday( &endCPU, NULL );
        double endProc = endCPU.tv_sec + ( endCPU.tv_usec / 1000000.0 );
        
        float result = 0;
        
        for(i=1;i<=J_ORDER;i++)
        {
            //printf("\nx[%d]=%f",i,X[i]);
            result += X[i]*MA[J_ROW_TEST+1][i];
            
        }
        
        //FINALIZA CONTAGEN DO TEMPO
        gettimeofday( &endTime, NULL );
        double end = endTime.tv_sec + ( endTime.tv_usec / 1000000.0 );
    
        printf("\nVERIFICACAO DO RESULTADO:\n");
        printf("ROW TEST: %f\n", result);
        printf("B[ROW TEST] = %f\n\n", MA[J_ROW_TEST + 1][J_ORDER+1]);
        
        printf( "Tempo de execução total: %.6lf segundos\n", end - start );
        printf( "Tempo de execução apenas de processamento: %.6lf segundos\n", endProc - startProc );
    }
    else{
        printf("ERRO ao abrir o arquivo\n");
    }
    
    return 0;
}